package middleware

import (
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"strings"
	"time"
	"xinyu/global"
	"xinyu/model/res"
	"xinyu/myerr"
	"xinyu/utils"
)

type Claims struct {
	AppKey    string `json:"app_key"`
	AppSecret string `json:"app_secret"`
	jwt.StandardClaims
}

func GetJwtSecret() []byte {
	return []byte(global.JWTSetting.Secret)
}

func GenerateToken(appKey, appSecret string) (string, error) {
	nowtime := time.Now()
	expireTime := nowtime.Add(global.JWTSetting.Expire)
	claims := Claims{
		AppKey:         utils.EncodeMD5(appKey),
		AppSecret:      utils.EncodeMD5(appSecret),
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expireTime.Unix(),
			Issuer: global.JWTSetting.Issuer,
		},
	}

	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	token, err := tokenClaims.SignedString(GetJwtSecret())
	return token, err
}

func ParseToken(token string) (*Claims, error) {
	tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return GetJwtSecret(), nil
	})
	if err != nil {
		return nil, err
	}

	if tokenClaims != nil {
		if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
			return claims, nil
		}
	}

	return nil, err
}

func JWT() gin.HandlerFunc {
	return func(c *gin.Context) {
		var (
			token string
			ecode = myerr.OK.Code
		)

		tokenHeader := c.Request.Header.Get("Authorization")
		if tokenHeader == "" {
			ecode = myerr.ErrValidation.Code
		} else {
			token = strings.Split(tokenHeader, " ")[1]
			_, err := ParseToken(token)
			if err != nil {
				ecode = myerr.ErrValidation.Code
			}
		}

		if ecode != myerr.OK.Code {
			res.SendResponse(c, myerr.ErrValidation, nil)
			c.Abort()
			return
		}

		c.Next()
	}
}